/**
 * @description: volatile 的读性能消耗与普通变量几乎相同，但是写操作稍慢，
 * 因为它需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行。
 * @author: zys
 * @create: 2020-10-11 20:36
 **/
public class TestVolatile {

    /**
     * volatile是轻量级的 synchronized 在多处理器开发中保证了共享变量的可见性
     * 如果volatile使用得当比使用synchronized 的执行成本更低 少了线程上下文切换操作
     * volatile可见性是因为进行了lock指令操作 将当前处理器缓存行数据回写到内存中  回写操作会使其他CPU 里缓存了该内存地址的数据无效
     * 缓存一致性
     */
    private static class VolatileVar implements Runnable {

        //有volatile和没volatile效果明显
        //private Boolean flag = true;
        private volatile Boolean flag = true;

        @Override
        public void run() {
            while (true) {
                //判断当为true的时候进入 当为false时不进入
                if (flag) {
                    System.out.println(Thread.currentThread().getName() + ":>>>>>" + flag);
                }
            }
        }
    }

    //模拟访问
    public static void main(String[] args) throws InterruptedException {
        VolatileVar v = new VolatileVar();
        Thread t1 = new Thread(v);
        Thread t2 = new Thread(v);
        Thread t3 = new Thread(v);
        Thread t4 = new Thread(v);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        Thread.sleep(500);
        v.flag = false;
        System.out.println("I sleep 3s");
        Thread.sleep(3000);
        System.out.println("I will start now");
        v.flag = true;
    }

    /**，volatile能保证修饰的变量的可见性和原子性，但不能保证变量的操作是原子性的，
     比如i++这些操作，看起来只有一步操作，但在jvm可执行的字节码中是不止一步的，
     因此依赖上一状态值的变量操作不宜用volatile修饰来确保线程安全，volatile还有其他作用就是防止jvm对代码的重排序*/

}
